package com.linkgie.galaxyframework.kvstorage;

/**
 * @author huanghaiquan
 *
 * @param <T>
 */
public interface KVMap<T> {

	/**
	 * 指定的键是否存在；
	 * 
	 * @param key
	 * @return
	 */
	boolean contains(String key);

	/**
	 * 指定的键是否存在；
	 * 
	 * @param key
	 * @return
	 */
	boolean contains(byte[] key);

	/**
	 * 以指定类型返回指定 key 的值；
	 * 
	 * <p>
	 * 如果键不存在，则返回 null；<br>
	 * 如果类型转换失败，则抛出 {@link DataCodecException} 异常；
	 * 
	 * @param key
	 * @return
	 */
	T get(String key);

	/**
	 * 以指定类型返回指定 key 的值；
	 * 
	 * <p>
	 * 如果键不存在，则返回 null；<br>
	 * 如果类型转换失败，则抛出 {@link DataCodecException} 异常；
	 * 
	 * @param key
	 * @return
	 */
	T get(byte[] key);

	/**
	 * 设置；
	 * <p>
	 * 插入操作时当指定的键（key）不存在时才写入参数指定的值（value）；
	 * <p>
	 * 如果指定的的键（key）已经存在，或指定的值（value）为 null ，则不做任何操作，直接返回 false；
	 * 
	 * @param key   键
	 * @param value 值；
	 * @return 返回成功标识；
	 *         <p>
	 *         如果为 true ，表示插入成功；<br>
	 *         如果为 false，表示未插入；
	 */
	void set(String key, T value);

	/**
	 * 设置；
	 * <p>
	 * 如果当指定的键（key）不存在时，则插入参数指定的值（value）；
	 * <p>
	 * 如果指定的的键（key）已经存在，则更新参数指定的值（value）；
	 * 
	 * @param key   键
	 * @param value 值；
	 */
	void set(byte[] key, T value);

	/**
	 * 插入；
	 * <p>
	 * 插入操作时当指定的键（key）不存在时才写入参数指定的值（value），写入成功后返回 true；
	 * <p>
	 * 如果指定的的键（key）已经存在，或指定的值（value）为 null ，则不做任何操作，直接返回 false；
	 * 
	 * @param key   键
	 * @param value 值；
	 * @return 返回成功标识；
	 *         <p>
	 *         如果为 true ，表示插入成功；<br>
	 *         如果为 false，表示未插入；
	 */
	boolean insert(String key, T value);

	/**
	 * 插入；
	 * <p>
	 * 插入操作时当指定的键（key）不存在时才写入参数指定的值（value），写入成功后返回 true；
	 * <p>
	 * 如果指定的的键（key）已经存在，或指定的值（value）为 null ，则不做任何操作，直接返回 false；
	 * 
	 * @param key   键
	 * @param value 值；
	 * @return 返回成功标识；
	 *         <p>
	 *         如果为 true ，表示插入成功；<br>
	 *         如果为 false，表示未插入；
	 */
	boolean insert(byte[] key, T value);

	/**
	 * 更新；
	 * <p>
	 * 更新操作是当指定的 key 已经存在时将值修改为指定的 value ，写入成功后返回 true；
	 * <p>
	 * 如果指定的 key 不存在，或指定的值为 null ，则不做任何操作，直接返回 false；
	 * 
	 * @param key   键；
	 * @param value 新值；
	 * @return 返回成功标识；
	 *         <p>
	 *         如果为 true ，表示 key 存在且值更新为指定的新值； <br>
	 *         如果为 false，表示 key 不存在，或者指定的值为 null；
	 */
	boolean update(String key, T value);

	/**
	 * 更新；
	 * <p>
	 * 更新操作是当指定的 key 已经存在时将值修改为指定的 value ，写入成功后返回 true；
	 * <p>
	 * 如果指定的 key 不存在，或指定的值为 null ，则不做任何操作，直接返回 false；
	 * 
	 * @param key   键；
	 * @param value 新值；
	 * @return 返回成功标识；
	 *         <p>
	 *         如果为 true ，表示 key 存在且值更新为指定的新值； <br>
	 *         如果为 false，表示 key 不存在，或者指定的值为 null；
	 */
	boolean update(byte[] key, T value);

	/**
	 * 删除；
	 * 
	 * @param key
	 */
	void delete(String key);

	/**
	 * 删除；
	 * 
	 * @param key
	 */
	void delete(byte[] key);

	/**
	 * 检索当前存储空间中包含指定前缀的所有键 ；
	 * <p>
	 * 检索的方式为升序检索；
	 * 
	 * @param keyPrefix 要检索的前缀；如果为 null 或者空字符，则返回当前存储的键空间下的全部键；
	 * @return
	 */
	KeyIterator<String, T> seekPrefixScope(String keyPrefix);

	/**
	 * 检索当前存储空间中包含指定前缀的所有键 ；
	 * <p>
	 * 检索的方式为升序检索；
	 * 
	 * @param keyPrefix 要检索的前缀；如果为 null 或者空字符，则返回当前存储的键空间下的全部键；
	 * @return
	 */
	KeyIterator<byte[], T> seekPrefixScope(byte[] keyPrefix);

	/**
	 * 升序前缀检索；<p>
	 * 
	 * 升序检索当前存储空间中从指定的“起点”（包含）开始的所有键；
	 * <p>
	 * 
	 * @param beginPrefix 起点前缀，可以是键或键的前缀；如果为空，则从存储空间的首个键开始检索；
	 * @return 大于等于“起点前缀”的所有键；
	 */
	default KeyIterator<String, T> prefixSeek(String beginPrefix) {
		return prefixSeek(beginPrefix, false, null, true);
	}

	/**
	 * 升序前缀检索；<p>
	 * 
	 * 升序检索当前存储空间中从指定的“起点”（包含）开始的所有键；
	 * <p>
	 * 
	 * @param beginPrefix 起点，可以是键或键的前缀；如果为空，则从存储空间的首个键开始检索；
	 * @return 大于等于“起点”的所有键；
	 */
	default KeyIterator<byte[], T> prefixSeek(byte[] beginPrefix) {
		return prefixSeek(beginPrefix, false, null, true);
	}

	/**
	 * 升序前缀检索；<p>
	 * 
	 * 升序检索当前存储空间中从指定的“起点”（包含）到“终点”（不包含）的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”小于“终点”（按自然顺序），否则返回的迭代器将不包含任何键；
	 * 
	 * @param beginPrefix 起点，可以是键或键的前缀；包含在返回结果中；如果为空，则从首个键开始检索；
	 * @param endPrefix   终点，可以是键或键的前缀；不包含在返回结果中；如果为空，则从起点开始检索余下的全部键；
	 * @return 大于等于“起点”且小于等于“终点”的所有键；
	 */
	default KeyIterator<String, T> prefixSeek(String beginPrefix, String endPrefix) {
		return prefixSeek(beginPrefix, false, endPrefix, true);
	}

	/**
	 * 升序前缀检索；<p>
	 * 
	 * 升序检索当前存储空间中从指定的“起点”（包含）到“终点”（不包含）的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”小于“终点”（按自然顺序），否则返回的迭代器将不包含任何键；
	 * 
	 * @param beginPrefix 起点，可以是键或键的前缀；包含在返回结果中；如果为空，则从首个键开始检索；
	 * @param endPrefix   终点，可以是键或键的前缀；不包含在返回结果中；如果为空，则从起点开始检索余下的全部键；
	 * @return 大于等于“起点”且小于“终点”的所有键；
	 */
	default KeyIterator<byte[], T> prefixSeek(byte[] beginPrefix, byte[] endPrefix) {
		return prefixSeek(beginPrefix, false, endPrefix, true);
	}

	/**
	 * 升序前缀检索；<p>
	 * 
	 * 升序检索当前存储空间中从指定的“起点”到“终点”的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”小于“终点”（按自然顺序），否则返回的迭代器将不包含任何键；
	 * 
	 * @param beginPrefix   起点，可以是键或键的前缀；如果为空，则从首个键开始检索；
	 * @param excludedStart 是否排除起点；
	 * @param endPrefix     终点，可以是键或键的前缀；如果为空，则从起点开始检索余下的全部键；
	 * @param excludedEnd   是否排除
	 * @return “起点”和“终点”之间的所有键；
	 */
	KeyIterator<String, T> prefixSeek(String beginPrefix, boolean excludedStart, String endPrefix, boolean excludedEnd);

	/**
	 * 升序前缀检索；<p>
	 * 
	 * 升序检索当前存储空间中从指定的“起点”到“终点”的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”小于“终点”（按自然顺序），否则返回的迭代器将不包含任何键；
	 * 
	 * @param beginPrefix   起点，可以是键或键的前缀；如果为空，则从首个键开始检索；
	 * @param excludedStart 是否排除起点；
	 * @param endPrefix     终点，可以是键或键的前缀；如果为空，则从起点开始检索余下的全部键；
	 * @param excludedEnd   是否排除
	 * @return “起点”和“终点”之间的所有键；
	 */
	KeyIterator<byte[], T> prefixSeek(byte[] beginPrefix, boolean excludedStart, byte[] endPrefix, boolean excludedEnd);

	/**
	 * 降序前缀检索；
	 * <p>
	 * 
	 * 降序检索当前存储空间中从指定的“起点”（包含）开始的所有键；
	 * <p>
	 * 
	 * @param beginPrefix 起点，可以是键或键的前缀；如果为空，则从存储空间最大的键开始检索；
	 * @return 小于等于“起点”的所有键；
	 */
	default KeyIterator<String, T> prefixSeekDesc(String beginPrefix) {
		return prefixSeekDesc(beginPrefix, false, null, true);
	}

	/**
	 * 降序前缀检索；
	 * <p>
	 * 
	 * 降序检索当前存储空间中从指定的“起点”（包含）开始的所有键；
	 * <p>
	 * 
	 * @param beginPrefix 起点，可以是键或键的前缀；如果为空，则从存储空间最大的键开始检索；
	 * @return 小于等于“起点”的所有键；
	 */
	default KeyIterator<byte[], T> prefixSeekDesc(byte[] beginPrefix) {
		return prefixSeekDesc(beginPrefix, false, null, true);
	}

	/**
	 * 降序前缀检索；
	 * <p>
	 * 
	 * 降序检索当前存储空间中从指定的“起点”（包含）到“终点”（不包含）的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”大于“终点”（按自然顺序），否则返回的迭代器将不包含任何键；
	 * 
	 * @param beginPrefix 起点，可以是键或键的前缀；包含在返回结果中；如果为空，则从最大的键开始检索；
	 * @param endPrefix   终点，可以是键或键的前缀；不包含在返回结果中；如果为空，则从起点开始检索余下的全部键；
	 * @return 小于等于“起点”且大于“终点”的所有键；
	 */
	default KeyIterator<String, T> prefixSeekDesc(String beginPrefix, String endPrefix) {
		return prefixSeekDesc(beginPrefix, false, endPrefix, true);
	}

	/**
	 * 降序前缀检索；
	 * <p>
	 * 
	 * 降序检索当前存储空间中从指定的“起点”（包含）到“终点”（不包含）的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”大于“终点”（按自然顺序），否则返回的迭代器将不包含任何键；
	 * 
	 * @param beginPrefix 起点，可以是键或键的前缀；包含在返回结果中；如果为空，则从最大的键开始检索；
	 * @param endPrefix   终点，可以是键或键的前缀；不包含在返回结果中；如果为空，则从起点开始检索余下的全部键；
	 * @return 小于等于“起点”且大于“终点”的所有键；
	 */
	default KeyIterator<byte[], T> prefixSeekDesc(byte[] beginPrefix, byte[] endPrefix) {
		return prefixSeekDesc(beginPrefix, true, endPrefix, true);
	}

	/**
	 * 降序前缀检索；
	 * <p>
	 * 
	 * 降序检索当前存储空间中从指定的“起点”到“终点”的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”大于“终点”（按自然顺序），否则返回的迭代器将不包含任何结果；
	 * 
	 * @param beginPrefix   起点，可以是键或键的前缀；如果为空，则从最后一个键开始检索；
	 * @param excludedStart 是否排除起点；
	 * @param endPrefix     终点，可以是键或键的前缀；如果为空，则从起点开始检索余下的全部键；
	 * @param excludedEnd   是否排除
	 * @return “起点”和“终点”之间的所有键；
	 */
	KeyIterator<String, T> prefixSeekDesc(String beginPrefix, boolean excludedStart, String endPrefix, boolean excludedEnd);

	/**
	 * 降序前缀检索；
	 * <p>
	 * 
	 * 降序检索当前存储空间中从指定的“起点”到“终点”的所有键；
	 * <p>
	 * 
	 * 调用者需要保证起“起点”大于“终点”（按自然顺序），否则返回的迭代器将不包含任何结果；
	 * 
	 * @param beginPrefix   起点，可以是键或键的前缀；如果为空，则从最后一个键开始检索；
	 * @param excludedStart 是否排除起点；
	 * @param endPrefix     终点，可以是键或键的前缀；如果为空，则从起点开始检索余下的全部键；
	 * @param excludedEnd   是否排除
	 * @return “起点”和“终点”之间的所有键；
	 */
	KeyIterator<byte[], T> prefixSeekDesc(byte[] beginPrefix, boolean excludedStart, byte[] endPrefix, boolean excludedEnd);

}